package yana.tpe.onlineshop.controller;

import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import yana.tpe.onlineshop.domain.domains.Category;
import yana.tpe.onlineshop.domain.domains.Product;
import yana.tpe.onlineshop.services.CategoryService;
import yana.tpe.onlineshop.services.ProductService;

/**
 *
 */
@Controller()
@RequestMapping(value = "admin", method = RequestMethod.GET)
public class AdminController extends AbstractController {

    @Autowired
    private CategoryService categoryService;
    @Autowired
    private ProductService productService;

    @RequestMapping(value = "", method = RequestMethod.GET)
    public String root(HttpServletRequest request) {
        logger.debug("Try to get root");
        return getRedirectBaseUrl(request, ADMIN) + CATEGORY + ROOT;
    }

    @RequestMapping(value = CATEGORY, method = RequestMethod.GET)
    public String categoryRoot(HttpServletRequest request) {
        logger.debug("Try to get root category");
        return getRedirectBaseUrl(request, ADMIN) + CATEGORY + ROOT;
    }

    @RequestMapping(value = CATEGORY + ID + PRODUCT + CHILD, method = RequestMethod.GET)
    public ModelAndView product(HttpServletRequest request, @PathVariable String id, @PathVariable String child) {
        logger.debug("Try to get child categories for [id={}]", id);

        Category category = getCategory(categoryService, id);
        logger.debug("Current category is {}", category);

        Product product = getProduct(productService, child);
        logger.debug("Current product is {}", product);

        ModelAndView mav = new ModelAndView("/admin", "class", "product");
        mav.addObject("categoriesTree", categoryService.getCategoryForEdit());
        mav.addObject("categoriesNavigation", categoryService.getCategoryWithParents(
                category != null ? category.getId() : null));
        mav.addObject("category", category);
        mav.addObject("product", product);
        mav.addObject("category_id", getCategoryId(category));
        mav.addObject("processingObjectClass", Product.class);
        mav.addObject("_type", "product");
        logger.debug("ModelAndView is {}", mav);

        return mav;
    }


    @RequestMapping(value = CATEGORY + ID, method = RequestMethod.GET)
    public ModelAndView category(HttpServletRequest request, @PathVariable String id) {
        logger.debug("Try to get child categories for [id={}]", id);

        Category category = getCategory(categoryService, id);
        logger.debug("Current category is {}", category);

        ModelAndView mav = new ModelAndView("/admin", "class", "category");
        mav.addObject("categoriesTree", categoryService.getCategoryForEdit());
        mav.addObject("category", category);
        mav.addObject("categories", categoryService.getChildCategoris(category));
        mav.addObject("products", productService.getProductFromCategory(category));
        mav.addObject("product", new Product());
        mav.addObject("category_id", getCategoryId(category));
        mav.addObject("processingObjectClass", Category.class);
        mav.addObject("_type", "category");
        logger.debug("ModelAndView is {}", mav);

        return mav;
    }

    @RequestMapping(value = CATEGORY + ID + ADD, method = RequestMethod.POST)
    public String addCategory(HttpServletRequest request, @PathVariable String id,
            @RequestParam(value = "name", defaultValue="New category", required=false) String name) {
        logger.debug("Try to add category to {}", id);
        categoryService.addCategory(extractIntegerId(id), new Category(name, null));
        return getRedirectBaseUrl(request, ADMIN) + CATEGORY + '/' + id;

    }

    @RequestMapping(value = CATEGORY + ID + UPDATE, method = RequestMethod.PUT)
    public String updateCategory(HttpServletRequest request, @PathVariable String id,
            @RequestParam("name") String name) {
        logger.debug("Try to update category [id={}] name to '{}'", id, name);
        categoryService.updateCategoryName(extractIntegerId(id), name);
        return getRedirectBaseUrl(request, ADMIN) + CATEGORY + '/' + id;

    }

    @RequestMapping(value = CATEGORY + ID + DELETE + CHILD, method = RequestMethod.DELETE)
    public String deleteCategory(HttpServletRequest request, @PathVariable String id, @PathVariable String child) {
        logger.debug("Try to delete category {}", id);
        categoryService.delete(Integer.parseInt(child));
        return getRedirectBaseUrl(request, ADMIN) + CATEGORY + '/' + id;

    }

    @RequestMapping(value = CATEGORY + ID + PRODUCT + ADD, method = RequestMethod.POST)
    public String addProduct(HttpServletRequest request, @PathVariable String id, @RequestParam String name, 
            @RequestParam String description, @RequestParam Double price,
            @RequestParam(required = false) MultipartFile image) throws IOException {
        logger.debug("Try to add product to category [id={}]", id);
        Product product = newProduct(null, name, description, price, image);
        productService.addProduct(extractIntegerId(id), product);
        return getRedirectBaseUrl(request, ADMIN) + CATEGORY + '/' + id;
    }

    @RequestMapping(value = PRODUCT + ID, method = RequestMethod.POST)
    public String updateProduct(HttpServletRequest request, @PathVariable Integer id, @RequestParam String name,
            @RequestParam String description, @RequestParam Double price,
            @RequestParam Integer categoryId, 
            @RequestParam(required = false) MultipartFile image) 
            throws IOException {

        logger.debug("Try to update product [id={}]", id);
        Product product = newProduct(id, name, description, price, image);

        productService.updateProduct(product, categoryId);

        return getRedirectBaseUrl(request, ADMIN) + CATEGORY + '/' + categoryId + PRODUCT + '/' + id;
    }

    @RequestMapping(value = CATEGORY + ID + PRODUCT + DELETE + CHILD, method = RequestMethod.DELETE)
    public String deleteProduct(HttpServletRequest request, @PathVariable String id, @PathVariable String child) {
        logger.debug("Try to delete category {}", id);
        productService.delete(Integer.parseInt(child));
        return getRedirectBaseUrl(request, ADMIN) + CATEGORY + '/' + id;

    }

    private Product newProduct(Integer id, String name, String description,
            Double price, MultipartFile image) throws IOException {
        Product product = new Product();
        product.setId(id);
        product.setName(name);
        product.setDescription(description);
        product.setPrice(price);
        product.setImage(image != null ? image.getBytes() : null);
        return product;
    }
}
